//
// Created by yinlixing on 2024/7/4.
//

#include "ring_buffer.h"

int rb_init(rb_control* control, void* buffer, int buffer_size, int unit_size)
{
    if(control == 0 || buffer == 0){
        return -1;
    }
    if(buffer_size<=0 || unit_size<=0){
        return 0;
    }

    control->_buffer = buffer;
    control->_pHead = 0;
    control->_pTail = control->_pHead + buffer_size;
    control->_unit_size = unit_size;
    rb_reset(control);
    return 0;
}

void rb_reset(rb_control* control)
{
    control->_pRead = control->_pWrite = control->_pHead = 0;
    control->_is_full = 0;
}

void* rb_get_write_buf(rb_control* control)
{
    void* result;
    if(control->_pWrite > control->_pRead){
        result = control->_buffer + control->_pWrite * control->_unit_size;
        control->_pWrite++;
        if(control->_pWrite == control->_pTail){
            control->_pWrite = control->_pHead;
        }
        if(control->_pWrite == control->_pRead){
            control->_is_full = 1;
        }
        return result;
    }else if(control->_pWrite < control->_pRead){
        result = control->_buffer + control->_pWrite * control->_unit_size;
        control->_pWrite++;
        if(control->_pWrite == control->_pRead){
            control->_is_full = 1;
        }
        return result;
    }else if(control->_pWrite == control->_pRead){
        if(control->_is_full == 1){
            return 0;
        }
        result = control->_buffer + control->_pWrite * control->_unit_size;
        control->_pWrite++;
        if(control->_pWrite == control->_pTail){
            control->_pWrite = control->_pHead;
        }
        return result;
    }
    return 0;
}

void* rb_get_read_buf(rb_control* control)
{
    void* result;
    if(control->_pWrite > control->_pRead){
        result = control->_buffer + control->_pRead * control->_unit_size;
        control->_pRead++;
        return result;
    }else if(control->_pWrite < control->_pRead){
        result = control->_buffer + control->_pRead * control->_unit_size;
        control->_pRead++;
        if(control->_pRead == control->_pTail){
            control->_pRead = control->_pHead;
        }
        return result;
    }else if(control->_pWrite==control->_pRead){
        if(control->_is_full == 0){
            return 0;
        }
        control->_is_full = 0;
        result = control->_buffer + control->_pRead * control->_unit_size;
        control->_pRead++;
        if(control->_pRead == control->_pTail){
            control->_pRead = control->_pHead;
        }
        return result;
    }
    return 0;
}

int rb_is_readable(rb_control* control)
{
    if(control->_is_full){
        return 1;
    }else{
        if(control->_pRead == control->_pWrite ){
            return 0;
        }else{
            return 1;
        }
    }
}

int rb_is_writeable(rb_control* control)
{
    if(control->_is_full){
        return 0;
    }else{
        return 1;
    }
}